package com.vcc.boss.controller;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.secure.totp.SaTotpUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import com.vcc.boss.core.component.RedisComponent;
import com.vcc.boss.core.component.SmsComponent;
import com.vcc.core.annotations.KycReject;
import com.vcc.core.annotations.ROReject;
import com.vcc.core.annotations.RestPack;
import com.vcc.core.exception.ProgramException;
import com.vcc.core.exception.SignInException;
import com.vcc.core.util.RegexUtil;
import com.vcc.data.entity.BossUser;
import com.vcc.service.boss.request.email.SendEmailDto;
import com.vcc.service.sa.BossUserUtil;
import com.vcc.service.service.BossUserService;
import org.apache.catalina.util.URLEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.Charset;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("email")
public class EmailController {

    @Autowired
    private BossUserService bossUserService;
    @Autowired
    private SmsComponent smsComponent;
    @Autowired
    private RedisComponent redisComponent;
    @Value("${spring.profiles.active}")
    private String activeProfile;

    @RestPack
    @ROReject
    @KycReject
    @PostMapping("sendEmail")
    public void sendEmail(@RequestBody SendEmailDto sendEmailDto) {
        if (RegexUtil.checkStringIsNull(sendEmailDto.getChannel())) {
            throw new ProgramException("渠道不能为空");
        }
        String code = UUID.randomUUID().toString().replace("-", "");
        if ("unLoginForgot".equals(sendEmailDto.getChannel())) {
            if (RegexUtil.checkObjectIsNull(sendEmailDto.getEmail())) {
                throw new ProgramException("邮箱不能为空");
            }
            if (RegexUtil.checkObjectIsNull(sendEmailDto.getCode())) {
                throw new ProgramException("谷歌验证码不能为空");
            }
            BossUser user = bossUserService.getByEmail(sendEmailDto.getEmail());
            if (!SaTotpUtil.validateTOTP(SaSecureUtil.aesDecrypt(user.getSalt(), user.getGoogleSecret()), sendEmailDto.getCode(), 1) && activeProfile.equals("prod")) {
//                if (!SaTotpUtil.validateTOTP(SaSecureUtil.aesDecrypt(user.getSalt(), user.getGoogleSecret()), sendEmailDto.getCode(), 1)) {
                Long increase = redisComponent.increase("check:error:count:" + user.getId(), 1L, 60L);
                if (increase >= 5) {
                    bossUserService.updateStatusById(user.getId(), 2);
                    throw new SignInException("验证失败次数过多，账户已被锁定");
                }
                throw new ProgramException("谷歌验证码不正确");
            }
            redisComponent.set("unLoginForgot:" + code, user.getId().toString(), 1L, TimeUnit.DAYS);
            smsComponent.sendUpdatePasswordEmail(user.getEmail(), encryptUrl(("unLoginForgot-" + code)));
        } else if ("updateEmail".equals(sendEmailDto.getChannel())) {
            BossUser user = bossUserService.getByIdOpt(BossUserUtil.getId()).orElseThrow(() -> new ProgramException("用户不存在"));
            if (RegexUtil.checkStringIsNull(sendEmailDto.getEmail()) || !Validator.isEmail(sendEmailDto.getEmail())) {
                throw new ProgramException("邮箱不能为空");
            }
            if (sendEmailDto.getEmail().equalsIgnoreCase(user.getEmail())) {
                throw new ProgramException("新邮箱不能与当前邮箱相同");
            }
            if (bossUserService.existsByEmail(sendEmailDto.getEmail())) {
                throw new ProgramException("当前邮箱已存在，无法修改");
            }
            StpUtil.checkSafe("UPDATE_EMAIL");
            if (redisComponent.hasKey("updateAccount:" + user.getId())) {
                throw new ProgramException("请勿频繁发送验证码，请稍后再试");
            }
            code = RandomUtil.randomNumbers(6);
            redisComponent.set("updateAccount:" + user.getId(), code + sendEmailDto.getEmail(), 5L, TimeUnit.MINUTES);
            smsComponent.sendUpdateAccountCodeEmail(sendEmailDto.getEmail(), code);
        } else {
            throw new ProgramException("渠道错误");
        }
    }

    private String encryptUrl(String url) {
        return new URLEncoder().encode(url, Charset.defaultCharset());
    }
}
